import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { DiscordSnowflake } from "@sapphire/snowflake";
import { plainToInstance } from "class-transformer";
import { Repository } from "typeorm";
import { ResultMsg } from "@/common/enum/result-msg.enum";
import Result from "@/common/utils/result.util";
import { SysPermission } from "@/database/entity/SysPermission";
import { MenuTreeVo } from "../menu/vo/menu-tree.vo";
import { CreatePermDto } from "./dto/create-perm.dto";
import { UpdatePermDto } from "./dto/update-perm.dto";

@Injectable()
export class PermService {
    constructor(@InjectRepository(SysPermission) private permRepository: Repository<SysPermission>) {}

    /** 新增系统权限 */
    async create(perm: CreatePermDto): Promise<Result<string>> {
        const id = DiscordSnowflake.generate().toString();
        const record = this.permRepository.create({ ...perm, id });
        await this.permRepository.save(record);
        return Result.success(id);
    }

    /** 删除系统权限 */
    async remove(id: string): Promise<Result<null>> {
        await this.permRepository.update(id, { deletedAt: new Date() });
        return Result.success(null, ResultMsg.DELETE_SUCCESS);
    }

    /** 更新系统权限 */
    async update(perm: UpdatePermDto): Promise<Result<null>> {
        const exist = await this.permRepository.findOneBy({ id: perm.id });
        if (!exist) {
            return Result.error(ResultMsg.DATA_NOT_FOUND);
        }
        await this.permRepository.save(perm);
        return Result.success(null, ResultMsg.DELETE_SUCCESS);
    }

    /** 列表查询并格式化成菜单类型 */
    async listMenus(): Promise<Array<MenuTreeVo>> {
        const permissions = await this.permRepository.find();
        const map = permissions.map((perm) => {
            return {
                ...perm,
                parentId: perm.menuId,
                path: "",
                meta: {
                    title: perm.name,
                    menuType: "button",
                    auth: perm.code,
                    rank: perm.rank,
                    remark: perm.remark,
                },
            };
        });
        return plainToInstance(MenuTreeVo, map, { excludeExtraneousValues: true });
    }

    /** 根据角色获取权限 */
    async listByRole(roles: string[]): Promise<string[]> {
        const perms = await this.permRepository
            .createQueryBuilder("perm")
            .select(["perm.code"])
            .innerJoin("sys_role_permission", "rp", "rp.perm_id = perm.id")
            .innerJoin("sys_role", "r", "r.id = rp.role_id")
            .where("r.code IN (:...roles)", { roles })
            .distinct(true)
            .getMany();
        return perms.map((perm) => perm.code);
    }
}
